package com.ity.teamanagement.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ity.teamanagement.code.ImgCode;
import com.ity.teamanagement.entity.OtherTeaImg;
import com.ity.teamanagement.entity.outputResult.TeaDetailsTempA;
import com.ity.teamanagement.entity.outputResult.TeaQrCodeTemp;
import com.ity.teamanagement.exception.ExceptionUtils;
import com.ity.teamanagement.mapper.TeaImgMapper;
import com.ity.teamanagement.mapper.TeaSearchMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author coderFu
 * @create 2021/5/4
 */

/**
 * CODE_WIDTH：二维码宽度，单位像素
 * CODE_HEIGHT：二维码高度，单位像素
 * FRONT_COLOR：二维码前景色，0x000000 表示黑色
 * BACKGROUND_COLOR：二维码背景色，0xFFFFFF 表示白色
 * 演示用 16 进制表示，和前端页面 CSS 的取色是一样的，注意前后景颜色应该对比明显，如常见的黑白
 * @author coderFu
 */
@Slf4j
@Component
public class TeaQrCodeUtils {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private TeaImgMapper teaImgMapper;

    @Resource
    private TeaSearchMapper teaSearchMapper;


    /**
     * 二维码存储的路径（内容）
     */
    private static String  URL = "" ;

    /**
     * 二维码的大小
     */
    private static final int CODE_WIDTH = 400;
    private static final int CODE_HEIGHT = 400;
    /**
     * 二维码的背景颜色
     */
    private static final int WHITE  = 0xFFFFFFFF;
    private static final int BLACK  = 0xFF000000;


    /**
     * 文字内容：扫码查看茶种信息
     */
    private static final int  WORD_HEIGHT = 400;
//    private static final String WORDS =  "扫码查看茶种信息";
    private static  final int MAX_WORDS_LENGTH = 10;


    /**
     * 根据茶种id生成二维码信息，因为配置是数据库动态设置此处不能为静态方法
     * @param id
     * @return
     */
    public  TeaQrCodeTemp createTeaQrCode(Long id){
        URL = (String)redisTemplate.opsForValue().get("URL")+id;
        TeaQrCodeTemp teaQrCodeTemp = new TeaQrCodeTemp();
        BufferedImage bufferedImage = null;

        /**com.google.zxing.EncodeHintType：编码提示类型,枚举类型
         * EncodeHintType.CHARACTER_SET：设置字符编码类型
         * EncodeHintType.ERROR_CORRECTION：设置误差校正
         *      ErrorCorrectionLevel：误差校正等级，L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
         *      不设置时，默认为 L 等级，等级不一样，生成的图案不同，但扫描的结果是一样的
         * EncodeHintType.MARGIN：设置二维码边距，单位像素，值越小，二维码距离四周越近
         * */
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.MARGIN,2);

        /**
         * MultiFormatWriter:多格式写入，这是一个工厂类，里面重载了两个 encode 方法，用于写入条形码或二维码
         *      encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
         *      contents:条形码/二维码内容
         *      format：编码类型，如 条形码，二维码 等
         *      width：码的宽度
         *      height：码的高度
         *      hints：码内容的编码类型
         * BarcodeFormat：枚举该程序包已知的条形码格式，即创建何种码，如 1 维的条形码，2 维的二维码 等
         * BitMatrix：位(比特)矩阵或叫2D矩阵，也就是需要的二维码
         */
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        //BitMatrix：位(比特)矩阵或叫2D矩阵，也就是需要的二维码
        BitMatrix bitMatrix = null;

        try{
            bitMatrix = multiFormatWriter.encode(URL, BarcodeFormat.QR_CODE,CODE_WIDTH,CODE_HEIGHT,hints);

            /**java.awt.image.BufferedImage：具有图像数据的可访问缓冲图像，实现了 RenderedImage 接口
             * BitMatrix 的 get(int x, int y) 获取比特矩阵内容，指定位置有值，则返回true，将其设置为前景色，否则设置为背景色
             * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
             *      x：像素位置的横坐标，即列
             *      y：像素位置的纵坐标，即行
             *      rgb：像素的值，采用 16 进制,如 0xFFFFFF 白色
             */
            bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < CODE_WIDTH; x++) {
                for (int y = 0; y < CODE_HEIGHT; y++) {
                    bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
                }
            }
            //存储二维码图片到本地磁盘
            //查询茶种名字
            TeaDetailsTempA tempTeaMessageA = teaSearchMapper.findTempTeaMessageA(id);
            String teaName = "";
            if (tempTeaMessageA.getChineseName().length()<=MAX_WORDS_LENGTH){
                teaName = tempTeaMessageA.getChineseName();
            }else {
                teaName = tempTeaMessageA.getChineseName().substring(0,10);
            }
            BufferedImage bufferedImage1 = insertWords(bufferedImage,teaName);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage1,"jpg",bos);
            MultipartFile multipartFile = new MockMultipartFile(+id+".jpg", bos.toByteArray());
            String imgPath = FileUtils.uploadFile(multipartFile);
            if (StringUtils.isEmpty(imgPath)){
                log.info("二维码存储失败");
                ExceptionUtils.error(com.ity.teamanagement.code.TeaQrCode.QR_CODE_PRODUCE_FAIL);
            }
            // 存储二维码图片到数据库
            OtherTeaImg otherTeaImg = new OtherTeaImg();
            Long aLong = teaImgMapper.findOtherImgMaxId();
            otherTeaImg.setOtherKeyId(aLong);
            otherTeaImg.setPath(imgPath);
            otherTeaImg.setCreateTime(new Date());
            Integer count = teaImgMapper.saveOtherImg(otherTeaImg);
            if (count<1){
                log.info("图片存储数据库失败");
                ExceptionUtils.error(ImgCode.IMG_UPDATE_ERROR);
            }
            teaQrCodeTemp.setContent(URL);
            teaQrCodeTemp.setTeaMessageId(id);
            teaQrCodeTemp.setQrImgId(aLong);
            teaQrCodeTemp.setPath(imgPath);
        }catch (Exception e){
            e.printStackTrace();
        }
        return teaQrCodeTemp;
    }



    /**
     *二维码下方插入文字
     * @param image 图片处理对象
     */
    public  BufferedImage  insertWords(BufferedImage image, String teaName) {
        //新的图片在二维码下方加入文字说明
        BufferedImage outImage = new BufferedImage(CODE_WIDTH,WORD_HEIGHT, BufferedImage.TYPE_INT_RGB);
        //获取绘图对象
        Graphics2D outg = outImage.createGraphics();
        //画二维码到新的面板
        outg.drawImage(image,0,0,image.getWidth(),image.getHeight(),null);
        //画文字到新的面板
//        Color color = new Color(183,183,183 );
        //设置颜色和画笔粗细
        outg.setColor(Color.black);
        outg.setStroke(new BasicStroke(5));
        //字体、字型、字号
        outg.setFont(new Font("微软雅黑",Font.PLAIN,18));
        //文字长度
        int strWidth = outg.getFontMetrics().stringWidth(teaName);
        //总长度减去文字长度的一半（居中显示）
        int wordStartX= (CODE_WIDTH-strWidth)/2;
        //height+(outImage.getHeight()-height)/2+12
        int wordStartY = CODE_HEIGHT-5;
        //画文字
        outg.drawString(teaName,wordStartX,wordStartY);
        outg.dispose();
        outImage.flush();
        return outImage;
    }
}



